'use strict';

module.exports = exec;

const path = require('path')
const cp = require('child_process')
const Package = require('@ayuan-cli/package')
const log = require('@ayuan-cli/log')

// 映射
const SETTINGS = {
    init: '@ayuan-cli/init'
}

const CACHE_DIR = 'dependencies'

// 兼容 windows 和 mac
function spawn(command, args, options) {
    const win32 = process.platform === 'win32'
    const cmd = win32 ? 'cmd' : command
    const cmdArgs = win32 ? ['/c'].concat(command, args) : args
    return cp.spawn(cmd, cmdArgs, options || {})
}


async function exec() {
    let targetPath = process.env.CLI_TARGET_PATH
    const homePath = process.env.CLI_HOME_PATH
    log.verbose('targetPath', targetPath)
    log.verbose('homePath', homePath)
    const cmdObj = arguments[arguments.length - 1]
    const cmdName = cmdObj.name()
    const packageName = SETTINGS[cmdName]
    const packageVersion = 'latest'
    let storeDir = ''
    let pkg = null
    // 开启子进程（多进程
    // 从 npm 动态 下载执行包
    if (!targetPath) {
        // 生成缓存目录
        targetPath = path.resolve(homePath, CACHE_DIR)
        storeDir = path.resolve(targetPath, 'node_modules')
        log.verbose('targetPath', targetPath)
        log.verbose('storeDir', storeDir)
        pkg = new Package({
            targetPath,
            homePath,
            packageName,
            packageVersion,
            storeDir
        })
        if (await pkg.exists()) {// 更新package
            await pkg.update()
        } else { // 安装package
            await pkg.install()
        }
    } else {
        pkg = new Package({
            targetPath,
            homePath,
            packageName,
            packageVersion,
        })
    }
    const rootFile = await pkg.getRootFilePath()
    if (rootFile) {
        try {
            let args = Array.from(arguments)
            let obj = Object.create(null)
            // 化简传入的 arguments 参数
            Object.keys(cmdObj).forEach((key) => {
                if (cmdObj.hasOwnProperty(key) && !key.startsWith('_') && key !== 'parent') {
                    obj[key] = cmdObj[key]
                }
            })
            args[args.length - 1] = obj
            const code = `require('${rootFile}').apply(null, ${JSON.stringify(args)})`
            const child = spawn('node', ['-e', code], {
                cwd: process.cwd(),
                stdio: 'inherit' // 子进程绑定父进程
            })
            // 监听错误
            child.on('error', (e) => {
                log.error(e.message)
            })
            // 监听退出
            child.on('exit', () => {
            })
        } catch (e) {
            console.error(e.message)
        }
    }
}
